import 'dart:io';

import 'package:path_provider/path_provider.dart';

/// 获取系统上喜欢的文件目录
class PathProviderUtils {
  /// 临时目录
  Directory? _tempDirectory;

  /// 应用程序可以在其中放置应用程序支持文件的目录的路径。
  Directory? _appSupportDirectory;

  /// 应用程序可以存储持久文件的目录的路径，只支持苹果 mac相关设备
  Directory? _appLibraryDirectory;

  /// 应用程序可能在其中放置用户生成的数据或应用程序无法重新创建的数据的目录路径。
  Directory? _appDocumentsDirectory;

  /// 应用程序可以访问顶级存储的目录的路径
  Directory? _externalStorageDirectory;

  /// 存储特定于应用程序的外部数据的目录的多个路径存储，只支持安卓
  List<Directory>? _externalStorageDirectories;

  /// 存储特定于应用程序的外部缓存数据的目录的多个路径存储，只支持安卓
  List<Directory>? _externalCacheDirectories;

  /// 工厂模式
  factory PathProviderUtils() => _getInstance();

  /// 单例
  static PathProviderUtils get instance => _getInstance();
  static PathProviderUtils? _instance;

  PathProviderUtils._internal();

  static PathProviderUtils _getInstance() => _instance ??= PathProviderUtils._internal();

  /// 设备上未备份的临时目录的路径，适用于存储下载文件的缓存。
  /// 此目录中的文件可以随时清除。 *不会*返回新的临时目录。 相反，调用者负责在此目录中创建（和清理）文件或目录。 此目录的作用域是调用应用程序。
  /// 在iOS上，它使用`NSCachesDirectory`API。
  /// 在Android上，它在上下文中使用`getCacheDir`API。
  Future<Directory?> get tempDirectory async => _tempDirectory ??= await getTemporaryDirectory();

  /// 应用程序可以存储持久文件的目录的路径，
  /// 已备份，并且用户不可见，例如sqlite.db。
  /// 在Android上，这个函数返回null, 在底层中返回[UnsupportedError]
  Future<Directory?> get appLibraryDirectory async {
    if (!Platform.isIOS && !Platform.isMacOS) {
      return null;
    }
    return _appLibraryDirectory ??= await getLibraryDirectory();
  }

  /// 应用程序可能在其中放置用户生成的数据或应用程序无法重新创建的数据的目录路径。
  /// 在iOS上，它使用`NSDocumentDirectory` API。 如果不是用户生成的数据，请考虑使用[getApplicationSupportDirectory]。
  /// 在Android上，它在上下文上使用`getDataDirectory` API。 如果要让用户看到数据，请考虑改用[getExternalStorageDirectory]。
  Future<Directory?> get appDocumentsDirectory async =>
      _appDocumentsDirectory ??= await getApplicationDocumentsDirectory();

  /// 应用程序可以在其中放置应用程序支持文件的目录的路径。
  /// 将此文件用于您不想向用户公开的文件。 您的应用不应将此目录用于用户数据文件。
  /// 在iOS上，它使用`NSApplicationSupportDirectory` API。 如果此目录不存在，则会自动创建。
  /// 在Android上，此函数在上下文中使用`getFilesDir` API。
  Future<Directory?> get appSupportDirectory async => _appSupportDirectory ??= await getApplicationSupportDirectory();

  /// 指向可以存储特定于应用程序的外部缓存数据的目录的路径存储。这些路径通常驻留在外部存储器上，如单独的分区或SD卡。手机可能有多个存储目录可用。
  /// 在发出此命令之前，函数调用，因为此功能仅在Android上可用。
  /// 在iOS上，此函数抛出一个不支持的错误，因为这是不可能的在应用程序的沙盒外访问
  /// 在Android上，它返回Context.getExternalCacheDirs（）或API级别低于19的Context.getExternalCacheDir（）。
  Future<List<Directory>?> get externalCacheDirectories async {
    if (!Platform.isAndroid) {
      return null;
    }
    return _externalCacheDirectories ??= await getExternalCacheDirectories();
  }

  /// 指向可以存储特定于应用程序的数据的目录的路径。这些路径通常驻留在外部存储器上，就像单独的分区一样或者SD卡。手机可能有多个可用的存储目录。
  /// 在发出此命令之前，应确定当前的操作系统函数调用，因为此功能仅在Android上可用。
  /// 在iOS上，此函数抛出一个不支持的错误，因为这是不可能的在应用程序的沙盒外访问。
  /// 在Android上，它返回Context.getExternalFilesDirs（字符串类型）或 API级别低于19的Context.getExternalFilesDir（字符串类型）。
  Future<List<Directory>?> get externalStorageDirectories async {
    if (!Platform.isAndroid) {
      return null;
    }
    return _externalStorageDirectories ??= await getExternalStorageDirectories();
  }

  /// 应用程序可以访问顶级存储的目录的路径。在发出此命令之前，应确定当前的操作系统
  /// 函数调用，因为此功能仅在Android上可用。在iOS上，此函数抛出一个[UnsupportedError]，因为这是不可能的
  /// 在应用程序的沙盒外访问。在Android上，它使用“getExternalFilesDir（null）”命令。
  Future<Directory?> get externalStorageDirectory async =>
      _externalStorageDirectory ?? await getExternalStorageDirectory();
}
